package netool

import (
	"github.com/go-netty/go-netty"
	"snow-im/app/constants/msgid"
	"snow-im/app/utils"
	"sync"
	"time"
)

var (
	once       = sync.Once{}
	connManner *ConnManager
)

type ConnManager struct {
	connections sync.Map
	idMaps      sync.Map
	authInfo    sync.Map
	beatInfo    sync.Map
}

func (this *ConnManager) SaveConnId(id int64, conn netty.Channel) {
	go this.CheckAuth(conn)
	//go this.CheckHeart(conn)
}

func (this *ConnManager)SetBeat(id int64)  {
	this.beatInfo.Store(id,time.Now().Unix())
}

func (this *ConnManager) CheckAuth(conn netty.Channel) {
	time.AfterFunc(time.Second*5, func() {
		var authData,_ = this.beatInfo.Load(conn.ID())
		if authData == nil{
			utils.Log(nil, "auth check fail", conn.ID())
			conn.Close()
		}
	})
}
func (this *ConnManager) CheckHeart(conn netty.Channel) {
	for {
		if conn.IsActive() == false{
			break
		}
		time.Sleep(10 * time.Second)
		var lastBeatInfo,_ = this.beatInfo.Load(conn.ID())
		var lastBeat int64 = 0
		if lastBeatInfo != nil{
			lastBeat = lastBeatInfo.(int64)
		}
		if time.Now().Unix() - lastBeat > 10{
			conn.Close()
			break
			utils.Log(nil,"heart check fail")
		}else{
			//回写心跳
			conn.Write(utils.PackMsg([]byte("hello"), msgid.HEART_BEAT))
		}
	}

}

func (this *ConnManager) SaveConnection(id string, channel netty.Channel) {
	this.connections.Store(id, channel)
	this.idMaps.Store(channel.ID(), id)
}

func (this *ConnManager) GetConnection(id string) netty.Channel {
	var channelsData, _ = this.connections.Load(id)
	if channelsData == nil {
		return nil
	} else {
		return channelsData.(netty.Channel)
	}
}
func (this *ConnManager) DelConnection(id int64) {
	var uid, _ = this.idMaps.Load(id)
	if uid != nil {
		this.connections.Delete(uid.(string))
		this.idMaps.Delete(id)
	}

}

func GetConnManagger() *ConnManager {
	once.Do(func() {
		connManner = &ConnManager{
		}
	})
	return connManner
}
